﻿using System;

namespace DAPNet
{
    public class ClickCorrectionStats
    {
        private SampleCollection declicked;

        private SampleCollection clicked;

        private SampleCollection samples;

        private SampleCollection clicking;

        private ClickDetection perfectDetection;


        public ClickCorrectionStats(SampleCollection declicked, SampleCollection clicked, SampleCollection samples, SampleCollection clicking, ClickDetection perfectDetection)
        {
            if (declicked.Count != samples.Count ||
                declicked.Count != perfectDetection.Count)
            {
                // TODO: EXCEPTION CONSIDERATION.
                throw new ArgumentException();
            }

            this.declicked = declicked;
            this.samples = samples;
            this.clicked = clicked;
            this.clicking = clicking;
            this.perfectDetection = perfectDetection;
        }

        public int Count
        {
            get
            {
                return samples.Count;
            }
        }

        public SampleCollection Declicked
        {
            get
            {
                return declicked;
            }
        }

        public SampleCollection Clicked
        {
            get
            {
                return clicked;
            }
        }

        public SampleCollection Samples
        {
            get
            {
                return samples;
            }
        }

        public SampleCollection Clicking
        {
            get
            {
                return clicking;
            }
        }

        public ClickDetection PerfectDetection
        {
            get
            {
                return perfectDetection;
            }
        }

        public double GetAvgAbsDifference()
        {
            return GetAvgAbsDifference(0, Count - 1);
        }

        public double GetAvgAbsDifference(int startIndex, int endIndex)
        {
            double sumAbsDifference = 0;
            double numPositives = 0;
            for (int i = startIndex; i <= endIndex; i++)
            {
                if (perfectDetection[i])
                {
                    double value = samples[i].Value;
                    double correctedValue = declicked[i].Value;
                    double absDifference = Math.Abs(correctedValue - value);
                    sumAbsDifference += absDifference;
                    numPositives++;
                }
            }
            double avgAbsDifference = sumAbsDifference / numPositives;
            return avgAbsDifference;
        }

        public double GetDeviationDifference()
        {
            return GetDeviationDifference(0, Count - 1);
        }

        public double GetDeviationDifference(int startIndex, int endIndex)
        {
            double sumSquaredDifference = 0;
            double sumDifference = 0;
            double numPositives = 0;
            for (int i = startIndex; i <= endIndex; i++)
            {
                if (perfectDetection[i])
                {
                    double value = samples[i].Value;
                    double correctedValue = declicked[i].Value;
                    double difference = correctedValue - value;
                    sumDifference += difference;
                    sumSquaredDifference += difference * difference;
                    numPositives++;
                }
            }
            double avgDifference = sumDifference / numPositives;
            double avgSquaredDifference = sumSquaredDifference / numPositives;
            double varianceDifference = avgSquaredDifference - (avgDifference * avgDifference);
            double deviationDifference = Math.Sqrt(varianceDifference);
            return deviationDifference;
        }
    }
}
